package com.lhkj.ct.framework.shiro.realm;

import com.google.common.collect.Sets;
import com.lhkj.ct.base.constants.SystemConstants;
import com.lhkj.ct.base.enums.GlobalStatus;
import com.lhkj.ct.base.model.LoginUser;
import com.lhkj.ct.base.model.UserAuthInfo;
import com.lhkj.ct.base.utils.IpUtils;
import com.lhkj.ct.base.utils.ServletUtils;
import com.lhkj.ct.framework.shiro.token.UsernamePasswordAuthToken;
import com.lhkj.ct.meta.modules.patient.mapper.PatientMapper;
import eu.bitwalker.useragentutils.UserAgent;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * <p>
 *     web用户登录授权
 * </p>
 */
public class PlatformAuthorizingRealm extends AuthorizingRealm {

    private static final Logger log = LoggerFactory.getLogger(PlatformAuthorizingRealm.class);

    @Resource
    private PatientMapper patientMapper;

    public PlatformAuthorizingRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
        super(cacheManager, matcher);
    }

    @Override
    public void setName(String name) {
        super.setName("platform_auth_realm");
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        if (!(token instanceof UsernamePasswordAuthToken)) return false;
        return Objects.equals(((UsernamePasswordAuthToken) token).getUserType(), Integer.valueOf(2));
    }

    /**
     * 授权权限
     *
     * 用户进行权限验证时候Shiro会去缓存中找,如果查不到数据,会执行这个方法去查权限,并放入缓存中
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        LoginUser user = (LoginUser) principals.getPrimaryPrincipal();
        authorizationInfo.setRoles(user.getShiroRoles());
        return authorizationInfo;
    }

    /**
     * 用户身份验证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordAuthToken webToken = (UsernamePasswordAuthToken) token;
        String username = webToken.getUsername();
        UserAuthInfo user = patientMapper.getUserAuthInfo(username);
        if (null == user) {
            throw new UnknownAccountException("账号或密码有误，请重新输入！");
        }
        if (user.getStatus() != GlobalStatus.NORMAL) {
            throw new DisabledAccountException("用户已封禁，请联系管理员！");
        }
        String ipAddr = IpUtils.getIpAddr();
        UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
        LoginUser loginUser = LoginUser.builder()
                .sessionKey(username)
                .userType(2)
                .userId(user.getUserId())
                .loginName(user.getUsername())
                .userName(user.getName())
                .shiroRoles(Sets.newHashSet(SystemConstants.PLAT_ROLE_CODE))
                .ipaddr(ipAddr)
                .loginLocation(IpUtils.getIpRegion(ipAddr))
                .loginTime(System.currentTimeMillis())
                .browser(userAgent.getBrowser().getName())
                .os(userAgent.getOperatingSystem().getName())
                .build();
        //4.设置账号为盐值
        ByteSource credentialsSalt = ByteSource.Util.bytes(SystemConstants.ACCOUNT_SALT);
        return new SimpleAuthenticationInfo(loginUser, user.getPassword(),
                credentialsSalt, getName());
    }



    //    /**
//     * 设置自定义认证加密方式
//     *
//     * @param credentialsMatcher 默认加密方式
//     */
//    @Override
//    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
//        //自定义认证加密方式
//        CustomCredentialsMatcher customCredentialsMatcher = new CustomCredentialsMatcher();
//        // 设置自定义认证加密方式
//        super.setCredentialsMatcher(customCredentialsMatcher);
//    }
}
